//
//  Module.swift
//  
//
//  Created by tank on 2021/10/9.
//

import Foundation
import Logging
import LibBase
import LibService

open class Module: ModuleProtocol {
    var logger = Logger(label: "LibModuleManager.Module")

    open class var type: String {
        return "module"
    }
    
    open class var pageClasses: [PageProtocol.Type] {
        return []
    }
    
    private var pages = [PageProtocol]()
    
    open class var handlerClasses: [HandlerProtocol.Type] {
        return []
    }
    
    private var handlers: [HandlerProtocol] = []
    
    
    public var type: String {
        return Self.type
    }
    
    public var id: String?
    
    
    required public init(id: String?) {
        self.id = id
        
        logger.logLevel = .debug
    }
    
    deinit {
        logger.debug("deinit Module type = \(type), id = \(id ?? "nil")")
    }
    
    open func page(type: String?,
                   id: String?,
                   config: PageConfig?,
                   params: [String: Any]?,
                   hash: String?) -> PageProtocol? {
        guard let pageClass = Self.pageClasses.first(where: { element in
            return type == nil || type == element.type
        }) else {
            return nil
        }
        
        if let page = pages.first(where: { element in
            return element.type == pageClass.type && element.id == id
        }) {
            return page
        }
        
        let page = pageClass.init(module: self, id: id,
                                  config: config,
                                  params: params, hash: hash)
        pages.append(page)
        
        return page
    }
    
    public func removePage(type: String, id: String?) {
        pages.removeAll { $0.type == type && $0.id == id }
        
        logger.debug("Remove page type = \(type), id = \(id ?? "null")")
        logger.debug("Page count: \(pages.count)")
        
        if pages.count == 0 {
            ModuleManager.shared.removeModule(type: self.type, id: self.id)
        }
    }
    
    open func handle(type: String?, params: [String: Any]?,
                     completion: RouterServiceProtocol.RouteCompletion?){
        guard let handlerClass = Self.handlerClasses.first(where: { element in
            return type == nil || type == element.type
        }) else {
            completion?(.error, nil)
            return
        }
        
        let handler = handlerClass.init(module: self)
        handlers.append(handler)
        
        handler.handle(params: params) { [weak self, weak handler] result, param in
            completion?(result, param)
            self?.handlers.removeAll { element in
                return element === handler
            }
        }
    }
}
